package edu.kit.csl.pisa.models;

import java.util.Arrays;

/*
This file is part of the PISA Alignment Tool.

Copyright (C) 2013
Karlsruhe Institute of Technology
Cognitive Systems Lab (CSL)
Felix Stahlberg

PISA is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

PISA is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with PISA. If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * Maximum likelihood sentence length model for P(trgtLength-srcLength).
 */
public class DifferenceSentenceLengthModel implements SentenceLengthModel {

	private Model4P alignmentModel;
	
	/* Model parameter (stored as 0,-1,1,-2,2...)
	 */
	private double[] l;
	
	private final int maxDifference2;
	
	/**
	 * Sole constructor. 
	 * 
	 * @param model alignment model
	 * @param maxDifference maximum difference between sentence lengths
	 */
	public DifferenceSentenceLengthModel(Model4P model, int maxDifference) {
		this.alignmentModel = model;
		maxDifference2 = maxDifference * 2;
		l = new double[maxDifference2 + 1];
		double prop = Math.log(1f / maxDifference2);
		Arrays.fill(l, prop);
	}

	/**
	 * Get the probability according the difference between source
	 * and target sentence length.
	 * {@inheritDoc}
	 */
	@Override
	public double getProbability(int nSrcWords, int nTrgtWords) {
		return l[getIndex(nSrcWords, nTrgtWords)];
	}
	
	/*
	 * Get array index for given sentence length difference.
	 */
	private int getIndex(int nSrcWords, int nTrgtWords) {
		int dist = 2 * (nSrcWords - nTrgtWords);
		return Math.min(maxDifference2, (dist < 0) 
				? (-dist - 1) : dist);
	}

	/* (non-Javadoc)
	 * @see SentenceLengthModel#count(double, int, int)
	 */
	@Override
	public void count(double weight, int nSrcWords, int nTrgtWords) {
		l[getIndex(nSrcWords, nTrgtWords)] += weight;
	}

	/**
	 * Use the alignment model given in the constructor to normalize the
	 * collected fractional counts.
	 * 
	 * @see #count(double, int, int)
	 */
	@Override
	public void normalize() {
		alignmentModel.normalize(l);
	}

	/**
	 * Uses {@link AlignmentModel#dumpParameter(String, Object[])} to dump
	 * the l parameter to the file system.
	 * 
	 * @param prefix prefix of the dump file to create
	 * @param postfix postfix of the dump file to create
	 * @see SentenceLengthModel#dumpToFilesystem(String, String)
	 */
	@Override
	public void dumpToFilesystem(String prefix, String postfix) {
		double[][] arr = new double[1][];
		arr[0] = l;
		alignmentModel.dumpParameter(prefix + "l" + postfix, arr);
	}
}
